package com.ssx.realms;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ssx.entity.Employees;
import com.ssx.mapper.RoleMapper;
import com.ssx.service.IEmployeesService;
import com.ssx.service.impl.EmployeesServiceImpl;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.realm.AuthenticatingRealm;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.Resource;
import java.util.HashSet;
import java.util.Set;

/**
 * @Package com.ssx.realms
 * @ClassName ShiroRealm
 * @Copyright: Copyright (c) 2020
 * @Date 2020/10/22 16:47
 * @Company www.sudaoxi.com.cn
 * @Author 苏道羲
 * @Version 1.0
 * @Description
 */
public class ShiroRealm extends AuthorizingRealm {
    @Autowired
    private IEmployeesService employeesService;
    @Autowired
    private RoleMapper roleMapper;

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("doGetAuthenticationInfo:" + token);
        //1.把AuthenticationToken转换为UsernamePasswordToken
        UsernamePasswordToken upToken = (UsernamePasswordToken) token;

        //2.从UsernamePasswordToken中获取username
        String username = upToken.getUsername();
        //3.调用数据库方法，从数据库中查询username对应的用户记录
        Employees employees = employeesService.getOne(new QueryWrapper<Employees>().eq("username", username));
        //session中存信息
        SecurityUtils.getSubject().getSession().setAttribute("emp", employees);
        //4.若用户不存在，则抛出UnknownAccountException异常
        if (employees == null) {
            throw new UnknownAccountException("用户不存在");
        }
        //5.根据用户信息的情况，决定是否要抛出其他的AuthenticationException异常

        //6.根据用户的情况，来构建AuthenticationToken对象并返回，通常使用SimpleAuthenticationInfo
        //以下信息是从数据库获取的。
        //6.1.principle：认证的实体信息。可以是username，数据表对应的实体类对象等
        //6.2.credentials：密码。
        //6.3.realmName：当前realm对象的name，调用父类的getName()方法即可
        //6.4.credentialsSalt：盐值。因为username唯一所以可以作为盐值
        ByteSource credentialsSalt = ByteSource.Util.bytes(username);

        return new SimpleAuthenticationInfo(username, employees.getPassword(), credentialsSalt, getName());
    }

    /*
    用于授权的方法
    授权会被shiro回调的方法
    */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //1.从PrincipleCollection中来获取登录用户的信息
        String username = (String)principalCollection.getPrimaryPrincipal();
        //2.利用登录的用户的信息来获取当前用户的角色或权限（可能需要查询数据库）
        Set<String> roles = roleMapper.getRoleNameByUsername(username);
        Set<String> permission=roleMapper.getPermissonByUsername(username);

        //3.创建SimpleAuthorizationInfo，并设置其reles属性
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.setStringPermissions(permission);
        info.setRoles(roles);
        //4.返回SimpleAuthorizationInfo对象
        return info;
    }

    public static void main(String[] args) {
        String username = "wangwu";
        String hashAlgorithmName = "MD5";
        Object source = "123456";
        Object salt = ByteSource.Util.bytes(username);
        int hashIterations = 1024;
        SimpleHash simpleHash = new SimpleHash(hashAlgorithmName, source, salt, hashIterations);
        String result = simpleHash.toString();
        System.out.println(result);//admin==038bdaf98f2037b31f1e75b5b4c9b26e||user==098d2c478e9c11555ce2823231e02ec1
    }
}
